package com.chuxing.system.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chuxing.domain.ClassInfo;
import com.chuxing.domain.DTO.ClassinfoListDTO;
import com.chuxing.domain.DTO.TClassListMembersDTO;
import com.chuxing.domain.DTO.TGroupsListDTO;
import com.chuxing.domain.TClassMembers;
import com.chuxing.domain.VO.PageResultVO;
import com.chuxing.exception.GenericException;
import com.chuxing.system.mapper.ClassinfoMapper;
import com.chuxing.system.mapper.TClassMembersMapper;
import com.chuxing.system.service.IClassinfoService;
import com.chuxing.system.service.ITClassMembersService;
import com.chuxing.system.service.ITGroupsService;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import lombok.RequiredArgsConstructor;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * 班级信息Service业务层处理
 * 
 * @author 刘祺
 * @date 2024-12-13
 */
@Service
@Transactional
@RequiredArgsConstructor
public class ClassinfoServiceImpl extends ServiceImpl<ClassinfoMapper, ClassInfo> implements IClassinfoService
{
    private final ClassinfoMapper classinfoMapper;
    private final ITClassMembersService iTClassMembersService;
    private final ITGroupsService iTGroupsService;
    private final TClassMembersMapper tClassMembersMapper;

    /**
     * 查询班级信息
     * 
     * @param id 班级信息主键
     * @return 班级信息
     */
    @Override
    @Cacheable(value = "classinfo", key = "'id'+#id")
    public ClassInfo selectClassinfoById(Long id)
    {
        return classinfoMapper.selectClassinfoById(id);
    }

    /**
     * 查询班级信息列表
     * 
     * @param classinfoListDTO 班级信息
     * @return 班级信息
     */
    @Override
    @Cacheable(value = "classinfo", key = "#classinfoListDTO")
    public PageResultVO selectClassinfoList(ClassinfoListDTO classinfoListDTO)
    {
        // 验证分页参数
        int pageNum = Math.max(1, classinfoListDTO.getPageNum());
        int pageSize = Math.max(1, classinfoListDTO.getPageSize());
        // 启用分页查询
        PageHelper.startPage(pageNum, pageSize);
        try {
            try (Page<ClassInfo> page = classinfoMapper.selectClassinfoList(classinfoListDTO)) {
                // 构造并返回分页结果对象
                return new PageResultVO(page.getTotal(), page.getResult());
            }
        } catch (Exception e) {
            // 抛出通用异常，不暴露具体错误信息
            throw new GenericException("系统内部错误");
        } finally {
            // 确保分页查询结束
            PageHelper.clearPage();
        }
    }

    /**
     * 新增班级信息
     * 当新增班级信息时，此方法会检查新班级是否应设置为默认班级如果当前数据库中已存在默认班级，
     * 则会首先将现有的默认班级的默认状态取消，确保任何时候都只有一个默认班级
     *
     * @param classinfo 班级信息，包括班级的各种属性，如名称、描述等
     * @return 插入结果，返回影响的行数，通常为1表示成功，其他值表示失败
     */
    @Override
    @CacheEvict(value = "classinfo",allEntries = true)
    public int insertClassinfo(ClassInfo classinfo)
    {
        // 检查新班级是否应设置为默认班级
        if(classinfo.getIsDefault()==1){
            // 查询当前是否已存在默认班级
            ClassInfo classInfo = classinfoMapper.selectClassinfoByIsDefault(1);
            if(classInfo!=null){
                // 如果存在，默认班级将不再是默认，更新其状态
                classInfo.setIsDefault(0L);
                classinfoMapper.updateClassinfo(classInfo);
            }
        }
        // 插入新的班级信息
        return classinfoMapper.insertClassinfo(classinfo);
    }

    /**
     * 修改班级信息
     * 当修改班级信息时，如果将某个班级设置为默认班级（isDefault设为1），
     * 则之前标记为默认的班级会被取消默认标记
     *
     * @param classinfo 班级信息，包含需要修改的班级详情
     * @return 结果，返回更新操作的影响行数
     */
    @Override
    @Caching(evict = {
            @CacheEvict(value = "classinfo",allEntries = true),
            @CacheEvict(value = "tClassMembersCache",allEntries = true)
    })
    public int updateClassinfo(ClassInfo classinfo)
    {
        // 检查是否有班级被设置为默认班级
        if(classinfo.getIsDefault()==1){
            // 查询当前标记为默认的班级
            ClassInfo classInfo = classinfoMapper.selectClassinfoByIsDefault(1);
            // 如果存在默认班级，取消其默认标记
            if(classInfo!=null){
                classInfo.setIsDefault(0L);
                classinfoMapper.updateClassinfo(classInfo);
            }
        }
        // 更新班级信息
        return classinfoMapper.updateClassinfo(classinfo);
    }

    /**
     * 批量删除班级信息
     * 
     * @param ids 需要删除的班级信息主键
     * @return 结果
     */
    @Override
    @CacheEvict(value = "classinfo",allEntries = true) // 使用缓存清除注解，删除所有班级信息缓存
    public int deleteClassinfoByIds(Long[] ids)
    {
        // 判断对应班级是否绑定了学生
        for (Long id : ids) {
            // 创建查询班级学生列表的DTO对象
            TClassListMembersDTO tClassListMembersDTO = new TClassListMembersDTO();
            tClassListMembersDTO.setClassID(id);
            // 设置分页参数
            tClassListMembersDTO.setPageNum(1);
            tClassListMembersDTO.setPageSize(Integer.MAX_VALUE);
            // 查询班级下的学生列表
            PageResultVO pageResultVO = iTClassMembersService.selectTClassList(tClassListMembersDTO);
            // 如果班级下有学生，则抛出异常，无法删除
            if (pageResultVO.getTotal() > 0) {
                throw new GenericException("班级下有学生，无法删除");
            }
            //查询班级下小组列表
            TGroupsListDTO tGroupsListDTO = new TGroupsListDTO();
            tGroupsListDTO.setPageNum(1);
            tGroupsListDTO.setPageSize(Integer.MAX_VALUE);
            tGroupsListDTO.setClassID(id);
            PageResultVO pageResultVO1 = iTGroupsService.selectTGroupsList(tGroupsListDTO);
            if(pageResultVO1.getTotal()>0){
                throw new GenericException("班级下有小组，无法删除");
            }
        }
        // 调用Mapper方法批量删除班级信息
        return classinfoMapper.deleteClassinfoByIds(ids);
    }

    /**
     * 根据是否默认查询班级信息
     * @param isDefault
     * @return
     */
    @Override
    @Cacheable(value = "classinfo",key = "'isDefault'+#isDefault")
    public ClassInfo selectClassinfoByIsDefault(int isDefault) {
        return classinfoMapper.selectClassinfoByIsDefault(isDefault);
    }

    /**
     * 根据学生ID获取班级信息列表
     *
     * 该方法使用Spring的Cacheable注解来缓存结果，以提高性能和减少数据库查询次数
     * 缓存的值存储在名为"classinfo"的缓存中，键为学生ID，这样可以确保每次查询相同学生ID时，都能从缓存中获取结果，而不是重新执行查询
     *
     * @param studentId 学生ID，用于查询班级信息
     * @return 包含班级信息的列表
     */
    @Override
    public List<ClassInfo> selectClassinfoMessageList(String studentId) {
        // 根据学生ID查询班级成员信息列表
        List<TClassMembers> list = tClassMembersMapper.selectTClassByStudentId(studentId);

        // 从班级成员信息列表中提取所有班级ID，并转换为long数组
        long[] classIds = list.stream().mapToLong(TClassMembers::getClassID).toArray();

        // 根据班级ID数组查询班级信息列表
        List<ClassInfo> classInfos =null;
        if (classIds.length>0) {
            classInfos = classinfoMapper.selectClassinfoByIds(classIds);
        }
        return classInfos;
    }

}
